Имеется прямоугольник размера 1×n, квадратики 1×1 которого закрашены
белым или черным цветом. По прямоугольнику можно построить "код" -
последовательность чисел, равных количеству подряд идущих черных квадратов
слева направо.
Например, код этого прямоугольника 2 3 2 8 1.
Однако количество белых квадратов нигде не учитывается (группы черных клеток
должны разделяться как минимум одной белой клеткой). Поэтому одному и тому же
коду может соответствовать несколько прямоугольников. Например, выше
приведенному коду также соответствует прямоугольник
Вам необходимо
подсчитать количество прямоугольников, удовлетворяющих заданному коду.
Вход. Первая строка
содержит количество тестов t (1 < t < 20). Каждая из следующих t строк содержит данные для одного
теста. Каждый тест начинается длиной прямоугольника n (1 ≤ n ≤
200). Затем идет k (0 ≤ k ≤ (n + 1) / 2) – количество чисел в коде. Далее идут k чисел, описывающих непосредственно
код.
Выход. Для каждого
теста вывести в отдельной строке одно число – количество прямоугольников,
удовлетворяющих заданному коду. Ответ всегда помещается в 50 знаковое целое.
Пример
входа |
Пример
выхода |
3 4 0 5 2 1 2 4 2 2 2 |
1 3 0 |
комбинаторика
Пусть имеется w
белых квадратов и g групп черных квадратов. Поскольку группы черных
квадратов не касаются, то должно существовать как минимум g – 1 белых
квадратов (если таковых не существует – то ответ 0). При этом w – (g
– 1) белых квадратов будут свободными, и их можно расположить в любом месте по
отношению к группам черных квадратов. Количество мест, по которым можно
расположить свободные белые квадраты, равно (g + 1). Это можно сделать способами. Здесь = – количество способов
расположить r одинаковых объектов по n разным местам, где каждое
место может содержать произвольное количество объектов (сочетания с повторениями). Таким образом
= =
Пример
Рассмотрим
второй тест. Существует три полосы длины 5 с кодом 1 2:
Число свободных белых
квадратов равно 1, число групп 2. Следовательно количество мест, куда можно
поставить 1 свободный белый квадрат, равно 3. Количество вариантов искомой
расстановки равно 3, так как свободный квадрат можно поставить на одно из 3
мест.
Воспользуемся
формулой. Число белых квадратов w = 2, число групп g = 2.
Количество полос равно = = 3.
Технически
задача сводится к вычислению биномиального коэффициента, значение которого не
помещается в 64-битный целый тип. Воспользуемся классом BigInteger.
int n, g, w, group[200];
int i, j, tests;
class BigInteger{ . . .};
BigInteger Cnk(int k, int n)
{
BigInteger res(1);
for(int i = 1; i <= k; i++)
res = res * (n - i + 1) / i;
return res;
}
Читаем
количество тестов tests. Для каждого теста считываем код в массив group,
параллельно суммируя количество черных квадратов. Вычитаем его из n,
получим число белых квадратов w. Если количество белых квадратов w меньше g
– 1, то полосы с таким кодом не существует. Иначе вычисляем и выводим результат
.
scanf("%d",&tests);
for(i = 0; i < tests; i++)
{
scanf("%d
%d",&n,&g);
w = 0;
for(j = 0; j
< g; j++)
{
scanf("%d",&group[j]);
w += group[j];
}
w = n - w;
if (w < g
- 1) printf("0");
else
Cnk(w-g+1,w+1).print();
printf("\n");
}
Java реализация
import java.util.*;
import java.math.*;
public class Main
{
static BigInteger Cnk(BigInteger n, BigInteger k)
{
BigInteger ONE = BigInteger.ONE, CnkRes = ONE;
if (k.compareTo(n.subtract(k)) > 0) k = n.subtract(k);
for(BigInteger i = ONE; i.compareTo(k) <= 0; i = i.add(ONE))
CnkRes =
CnkRes.multiply(n.subtract(i).add(ONE)).divide(i);
return CnkRes;
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
int tests = con.nextInt();
int group[] = new int[200];
while(tests-- > 0)
{
int n = con.nextInt(), g = con.nextInt();
int w = 0;
for(int j = 0; j < g; j++)
{
group[j] = con.nextInt();
w += group[j];
}
w = n - w;
if (w < g - 1) System.out.println("0");
else System.out.println(Cnk(BigInteger.valueOf(w+1),
BigInteger.valueOf(w-g+1)));
}
}
}